////////////////////////////////////////////////////////////////////
// File:	Mesh.h
// Purpose: Defines the components of a mesh and a skinned mesh
//			seperately so the MeshManager can retrieve/access data and
//			manipulate it relatively easily.
// Author:	Jay Baird
////////////////////////////////////////////////////////////////////

#ifndef MESH_H
#define MESH_H

#include "MeshComponents.h"

enum MeshType
{
	MESH_TYPE_NULL = -1,
	MESH_TYPE_REGULAR = 1,
	MESH_TYPE_QUAD,
	MESH_TYPE_SKINNED_MESH,
	MESH_TYPE_MAX
};

class MeshManager;
class Mesh
{
friend MeshManager;
protected:
	unsigned m_numTriangles;
	unsigned m_numVertices;
	int m_textureID;
	MeshComponent::Triangle* m_triangles;
	Vec3* m_vertices;
	Vec3* m_normals;
	Vec2* m_texCoords;
	vec2 m_texTiles;
	MeshComponent::Buffer m_buffer;

	// Deletes any allocated memory associated with the mesh
	// Ins: None
	// Outs: None
	// Return: None
	void Delete();

public:
	Mesh() : m_triangles(0), m_texCoords(0), m_vertices(0), m_normals(0),
			 m_numVertices(0), m_numTriangles(0), m_textureID(-1), m_texTiles(1) { }
	virtual ~Mesh() { Delete(); }

	inline unsigned GetTriangleCount() const { return m_numTriangles; }
	inline unsigned GetVertexCount() const { return m_numVertices; }
	inline int GetTextureID() const { return m_textureID; }
	inline vec2 GetTextureTileCount() const { return m_texTiles; }

	inline const MeshComponent::Triangle* GetTriangles() const { return m_triangles; }
	inline const Vec2* GetTexCoords() const { return m_texCoords; }
	inline const Vec3* GetVertices() const { return m_vertices; }
	inline const Vec3* GetNormals() const { return m_normals; }
	inline unsigned GetBufferID(MeshComponent::MeshBufferType meshType) { return m_buffer.buffers[meshType]; }

	inline virtual MeshType Type() { return MESH_TYPE_REGULAR; }
};

class SkinnedMesh : public Mesh
{
friend MeshManager;
protected:
	unsigned m_numBones;
	MeshComponent::Bone* m_bones;	// transforms (bones)

	// m_influences[vertex][influence]			(numVertices & numInfluences)
	std::vector<std::vector<MeshComponent::Influence>> m_influences;	// 2D Array of (BoneIndices & weights)

	// Deletes any allocated memory associated with the mesh
	// Ins: None
	// Outs: None
	// Return: None
	void Delete()
	{
		if(m_bones) delete[] m_bones;
		m_bones = NULL;

		m_influences.clear();

		// Call parent's delete
		Mesh::Delete();
	}

public:
	SkinnedMesh() : m_bones(0), m_numBones(0) { }
	SkinnedMesh(const Mesh& m);
	SkinnedMesh& operator=(const Mesh& m);
	~SkinnedMesh() { Delete(); }

	inline unsigned GetBoneCount() const { return m_numBones; }

	inline const std::vector<std::vector<MeshComponent::Influence>>* GetInfluences() const { return &m_influences; }
	inline const MeshComponent::Bone* GetBones() const { return m_bones; }

	inline MeshType Type() { return MESH_TYPE_SKINNED_MESH; }
};



#endif